package com.ruoyi.system.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.CommonStreamUtil;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.dto.Web.BasketBallPlayerDto;
import com.ruoyi.system.domain.dto.Web.BasketBallPlayerExcel;
import com.ruoyi.system.domain.dto.Web.PlayerMoveDto;
import com.ruoyi.system.mapper.BaseCoachMapper;
import com.ruoyi.system.mapper.BaseContestMapper;
import com.ruoyi.system.mapper.BaseTournamentMapper;
import com.ruoyi.system.service.IBaseAttendanceLogService;
import com.ruoyi.system.service.IBaseBasketballTeamService;
import com.ruoyi.system.service.IBasketballPlayerAndTeamService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.mapper.BaseBasketballPlayerMapper;
import com.ruoyi.system.service.IBaseBasketballPlayerService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 球员Service业务层处理
 *
 * @author wangbj
 * @date 2024-04-16
 */
@Service
public class BaseBasketballPlayerServiceImpl extends ServiceImpl<BaseBasketballPlayerMapper, BaseBasketballPlayer> implements IBaseBasketballPlayerService {
    @Resource
    private BaseBasketballPlayerMapper baseBasketballPlayerMapper;

    @Resource
    private IBaseBasketballTeamService iBaseBasketballTeamService;

    @Resource
    private IBasketballPlayerAndTeamService iBasketballPlayerAndTeamService;

    @Resource
    private BaseContestMapper baseContestMapper;

    @Resource
    RedisService redisService;

    @Resource
    TokenService tokenService;
    @Resource
    LoginUserSetUtil loginUserSetUtil;

    @Resource
    private IBaseAttendanceLogService iBaseAttendanceLogService;

    @Resource
    private BaseTournamentMapper tournamentMapper;
    @Resource
    private BaseCoachMapper baseCoachMapper;

    /**
     * 查询球员
     *
     * @param id 球员主键
     * @return 球员
     */
    @Override
    public BaseBasketballPlayer selectBaseBasketballPlayerById(Long id) {
        return baseBasketballPlayerMapper.selectBaseBasketballPlayerById(id);
    }

    /**
     * 查询球员列表
     *
     * @param baseBasketballPlayer 球员
     * @return 球员
     */
    @Override
    public List<BaseBasketballPlayer> selectBaseBasketballPlayerList(BaseBasketballPlayer baseBasketballPlayer) {
        AssertUtil.notNull(baseBasketballPlayer.getPlayerId(), "球队id不能为空");
        return baseBasketballPlayerMapper.selectBaseBasketballPlayerList(baseBasketballPlayer);
    }

    /**
     * 新增球员
     *
     * @param baseBasketballPlayer 球员
     * @return 结果
     */
    @Override
    public int insertBaseBasketballPlayer(BaseBasketballPlayer baseBasketballPlayer) {
        AssertUtil.notNull(baseBasketballPlayer.getPlayerId(), "球队id不能为空");
        AssertUtil.assertNotBlank(baseBasketballPlayer.getPlayerNumber(), "球衣号码不能为空");
        BaseBasketballTeam byId = iBaseBasketballTeamService.getById(baseBasketballPlayer.getPlayerId());
        AssertUtil.notNull(byId, "球队没有找到!");


        checkPlayerNum(baseBasketballPlayer, null);

        loginUserSetUtil.populateFields(baseBasketballPlayer, 1);

        baseBasketballPlayer.setCreateTime(DateUtils.getNowDate());
        int i = baseBasketballPlayerMapper.insert(baseBasketballPlayer);

        if (Objects.nonNull(baseBasketballPlayer.getTournamentId())) {
            BaseAttendanceLog build = BaseAttendanceLog.builder().basketballTeamId(baseBasketballPlayer.getPlayerId())
                    .tournamentId(baseBasketballPlayer.getTournamentId())
                    .playerNumber(baseBasketballPlayer.getPlayerNumber())
                    .basketballPlayerId(baseBasketballPlayer.getId())
                    .organizationId(SecurityUtils.getOrganizationId())
                    .contestId(byId.getLeagueId())
                    .isAttendance(1L)
                    .build();
            loginUserSetUtil.populateFields(build, 1);
            iBaseAttendanceLogService.save(build);
        }

        iBasketballPlayerAndTeamService.save(BasketballPlayerAndTeam.builder()
                .playerId(baseBasketballPlayer.getId())
                .teamId(baseBasketballPlayer.getPlayerId())
                .type(0L)
                .contestId(byId.getLeagueId())
                .build());
        return i;
    }

    private void checkPlayerNum(BaseBasketballPlayer baseBasketballPlayer, Long id) {

        if (!baseBasketballPlayer.getPlayerNumber().matches("[0-9]+")) {
            throw new RuntimeException("球号输入错误！");
        }
        List<BaseBasketballPlayer> baseBasketballPlayers = baseBasketballPlayerMapper.getPlayerAll(baseBasketballPlayer.getPlayerId());
        if (CollectionUtil.isEmpty(baseBasketballPlayers)) {
            return;
        }
        long count1 = baseBasketballPlayers.stream().filter(
                vo -> Objects.equals(vo.getPlayerNumber(), baseBasketballPlayer.getPlayerNumber()) && !Objects.equals(vo.getId(), id)
        ).count();
        if (count1 != 0) {
            throw new RuntimeException("当前球队的球员号码已存在,不可重复");
        }

        if (Objects.equals(baseBasketballPlayer.getIsUp(), 1)) {
            long count = baseBasketballPlayers.stream().filter(vo -> Objects.equals(vo.getIsUp(), 1) && !Objects.equals(vo.getId(), id)).count();
            //暂定五个首发
            Long scoringWay = 0l;
            Long contestId = tokenService.getLoginUser().getContestId();
//            Long contestId =47l;
            if (redisService.hasKey(BaseContestServiceImpl.CONTEST_PREFIX_ID.concat(contestId.toString()))) {
                BaseContest baseContest = redisService.getCacheObject(BaseContestServiceImpl.CONTEST_PREFIX_ID.concat(contestId.toString()));
                scoringWay = baseContest.getScoringWay();
            } else {
                BaseContest baseContest = baseContestMapper.selectBaseContestById(contestId);
                scoringWay = baseContest.getScoringWay();
                redisService.setCacheObject(BaseContestServiceImpl.CONTEST_PREFIX_ID.concat(contestId.toString()), baseContest);
            }

            if (count >= (scoringWay == 0l ? 5l : 3l)) {
                throw new RuntimeException("当前球队首发已有" + (scoringWay == 0l ? "五" : "三") + "位!请先取消首发");
            }
        }
    }

    /**
     * 修改球员
     *
     * @param baseBasketballPlayer 球员
     * @return 结果
     */
    @Override
    public boolean updateBaseBasketballPlayer(BaseBasketballPlayer baseBasketballPlayer) {
        //更新首发位置 需要球队id
        if (ObjectUtil.isNotNull(baseBasketballPlayer.getIsUp())) {
            AssertUtil.notNull(baseBasketballPlayer.getPlayerId(), "球队id不能为空");
        }
        if (ObjectUtil.isNotNull(baseBasketballPlayer.getIsUp()))
            checkPlayerNum(baseBasketballPlayer, baseBasketballPlayer.getId());
        baseBasketballPlayer.setUpdateTime(DateUtils.getNowDate());
//        loginUserSetUtil.populateFields(baseBasketballPlayer,2);
        return this.updateById(baseBasketballPlayer);
    }

    /**
     * 批量删除球员
     *
     * @param ids 需要删除的球员主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteBaseBasketballPlayerByIds(Long[] ids) {
        iBasketballPlayerAndTeamService.remove(Wrappers.<BasketballPlayerAndTeam>lambdaQuery()
                .in(BasketballPlayerAndTeam::getPlayerId, ids)
                .eq(BasketballPlayerAndTeam::getType, 0));
        return baseBasketballPlayerMapper.deleteBaseBasketballPlayerByIds(ids);
    }

    /**
     * 删除球员信息
     *
     * @param id 球员主键
     * @return 结果
     */
    @Override
    public int deleteBaseBasketballPlayerById(Long id) {
        return baseBasketballPlayerMapper.deleteBaseBasketballPlayerById(id);
    }

    @Override
    public boolean getIsUp(Long teamOneId, Long teamTwoId, Integer num) {
        List<BasketballPlayerAndTeam> list = iBasketballPlayerAndTeamService.list(Wrappers.<BasketballPlayerAndTeam>lambdaQuery()
                .in(BasketballPlayerAndTeam::getTeamId, teamOneId, teamTwoId)
                .eq(BasketballPlayerAndTeam::getType, 0)
        );
        if (CollUtil.isEmpty(list)) {
            return true;
        }
        Map<Long, List<BasketballPlayerAndTeam>> collect = list.stream().collect(Collectors.groupingBy(BasketballPlayerAndTeam::getTeamId));
        List<BasketballPlayerAndTeam> basketballPlayerAndTeams1 = collect.get(teamOneId);
        List<BasketballPlayerAndTeam> basketballPlayerAndTeams2 = collect.get(teamTwoId);
        if (CollUtil.isEmpty(basketballPlayerAndTeams1) || CollUtil.isEmpty(basketballPlayerAndTeams2)) {
            return true;
        }
        List<Long> collect1 = basketballPlayerAndTeams1.stream().map(BasketballPlayerAndTeam::getPlayerId).collect(Collectors.toList());
        List<Long> collect2 = basketballPlayerAndTeams2.stream().map(BasketballPlayerAndTeam::getPlayerId).collect(Collectors.toList());

        List<BaseBasketballPlayer> list1 = this.list(Wrappers.<BaseBasketballPlayer>lambdaQuery()
                .in(BaseBasketballPlayer::getId, collect1)
                .eq(BaseBasketballPlayer::getIsUp, 1));

        List<BaseBasketballPlayer> list12 = this.list(Wrappers.<BaseBasketballPlayer>lambdaQuery()
                .in(BaseBasketballPlayer::getId, collect2)
                .eq(BaseBasketballPlayer::getIsUp, 1));

        if (CollUtil.isEmpty(list1) || list1.size() < num) {
            return true;
        }
        if (CollUtil.isEmpty(list12) || list12.size() < num) {
            return true;
        }
        return false;
    }

    @Override
    public List<BaseBasketballPlayer> playerList(BasketBallPlayerDto basketBallPlayerDto) {
        return baseMapper.playerList(basketBallPlayerDto);
    }

    @Override
    public List<BaseBasketballTeam> playerTeamList(Long contestId,String teamName) {
        return iBaseBasketballTeamService.playerTeamList(contestId,teamName);
    }

    @Override
    public String importPlayer(List<BasketBallPlayerExcel> playerList, String operName, Long contestId) {
        if (StringUtils.isNull(playerList) || playerList.size() == 0) {
            throw new ServiceException("导入用户数据不能为空！");
        }
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        Map<String, List<BasketBallPlayerExcel>> teamNameMap = CommonStreamUtil.group(playerList, BasketBallPlayerExcel::getTeamName);
        List<BaseBasketballTeam> teamList = iBaseBasketballTeamService.selectByTeamName(contestId,teamNameMap.keySet());
        if (CollUtil.isEmpty(teamList)) {
            failureMsg.append(playerList.size()+"条数据全部导入失败!,未找到对应球队");
            return failureMsg.toString();
        }
        Map<String, BaseBasketballTeam> stringBaseBasketballTeamMap = CommonStreamUtil.toMap(teamList, BaseBasketballTeam::getTeamName);

        int successNum = 0;
        int failureNum = 0;

        for (String key : teamNameMap.keySet()) {
            List<BasketBallPlayerExcel> basketBallPlayerExcels = teamNameMap.get(key);
            if (!stringBaseBasketballTeamMap.containsKey(key)) {
                failureNum = failureNum + teamNameMap.get(key).size();
                failureMsg.append(teamNameMap.get(key).size()+"条数据导入失败!,未找到对应球队");
            }
            BaseBasketballTeam team = stringBaseBasketballTeamMap.get(key);
            Long teamId = team.getId();
            for (BasketBallPlayerExcel excel : basketBallPlayerExcels) {
                try {
                    excel.setSex(Objects.equals(excel.getSex(),1L)?0L:1L);
                    Integer playerNumberNum = baseMapper.selectByPlayerNumber(teamId, excel.getPlayerNumber());
                    if (playerNumberNum != 0) {
                        throw new ServiceException("球员" + excel.getName() + "的号码" + excel.getPlayerNumber() + "在当前队伍" + team.getTeamName() + "已存在!");
                    }
                    BaseBasketballPlayer baseBasketballPlayer = BeanUtil.copyProperties(excel, BaseBasketballPlayer.class);
                    baseBasketballPlayer.setPlayerId(teamId);
                    loginUserSetUtil.populateFields(baseBasketballPlayer, 1);
                    baseBasketballPlayerMapper.insert(baseBasketballPlayer);
                    iBasketballPlayerAndTeamService.save(BasketballPlayerAndTeam.builder()
                            .playerId(baseBasketballPlayer.getId())
                            .teamId(baseBasketballPlayer.getPlayerId())
                            .type(0L)
                            .contestId(contestId)
                            .build());
                    successNum++;
                } catch (Exception e) {
                    failureNum++;
                    String msg = excel.getName() + "导入失败:";
                    failureMsg.append(msg + e.getMessage());
                    log.error(msg, e);
                }
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据导入成功！共 " + successNum + " 条");
        }
        return successMsg.toString();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean movePlayer(PlayerMoveDto dto) {
        if (Objects.equals(dto.getContestId(), dto.getTargetContestId())) {
            throw new ServiceException("迁移目标联赛不能与源联赛相同!");
        }
        BaseBasketballTeam team = iBaseBasketballTeamService.getBaseMapper().selectById(dto.getTeamId());
        if (Objects.isNull(team)) {
            throw new ServiceException("迁移球队异常!");
        }
        LambdaQueryWrapper<BaseBasketballTeam> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BaseBasketballTeam::getIsDeleted, 0);
        queryWrapper.eq(BaseBasketballTeam::getTeamName, team.getTeamName());
        queryWrapper.eq(BaseBasketballTeam::getLeagueId, dto.getTargetContestId());
        queryWrapper.last("limit 1");
        BaseBasketballTeam basketballTeam = iBaseBasketballTeamService.getBaseMapper().selectOne(queryWrapper);
        if (ObjectUtil.isNotNull(basketballTeam)) {
            throw new ServiceException("迁移目标联赛,球队名称已存在!");
        }
        BaseBasketballTeam targetTeam = new BaseBasketballTeam();
        BeanUtil.copyProperties(team, targetTeam);
        targetTeam.setId(null);
        targetTeam.setLeagueId(dto.getTargetContestId());
        loginUserSetUtil.populateFields(team, 1);
        iBaseBasketballTeamService.getBaseMapper().insert(targetTeam);

        List<BasketballPlayerAndTeam> basketballPlayerAndTeams = iBasketballPlayerAndTeamService.selectByTeamId(dto.getContestId(), team.getId());
        List<BasketballPlayerAndTeam> playerList = CommonStreamUtil.filter(basketballPlayerAndTeams, bo -> Objects.equals(bo.getType(), 0L));
        List<BasketballPlayerAndTeam> coachList = CommonStreamUtil.filter(basketballPlayerAndTeams, bo -> Objects.equals(bo.getType(), 1L));
        List<BasketballPlayerAndTeam> targetPlayerTeamList = new ArrayList<>();
        //同步球员
        if (CollUtil.isNotEmpty(playerList)) {
            List<BaseBasketballPlayer> baseBasketballPlayers = baseMapper.selectBatchIds(CommonStreamUtil.transSet(playerList, BasketballPlayerAndTeam::getPlayerId));
            baseBasketballPlayers.forEach(item -> {
                BaseBasketballPlayer baseBasketballPlayer = BeanUtil.copyProperties(item, BaseBasketballPlayer.class);
                loginUserSetUtil.populateFields(baseBasketballPlayer, 1);
                baseBasketballPlayer.setId(null);
                baseBasketballPlayerMapper.insert(baseBasketballPlayer);
                BasketballPlayerAndTeam playerAndTeam = BasketballPlayerAndTeam.builder()
                        .playerId(baseBasketballPlayer.getId())
                        .teamId(targetTeam.getId())
                        .type(0L)
                        .contestId(dto.getTargetContestId())
                        .build();
                targetPlayerTeamList.add(playerAndTeam);
            });

        }
        //同步教练
        if (CollUtil.isNotEmpty(coachList)) {
            List<BaseCoach> baseCoaches = baseCoachMapper.selectBatchIds(CommonStreamUtil.transSet(coachList, BasketballPlayerAndTeam::getPlayerId));
            baseCoaches.forEach(item -> {
                BaseCoach coach = BeanUtil.copyProperties(item, BaseCoach.class);
                loginUserSetUtil.populateFields(coach, 1);
                coach.setId(null);
                baseCoachMapper.insert(coach);
                BasketballPlayerAndTeam playerAndTeam = BasketballPlayerAndTeam.builder()
                        .playerId(coach.getId())
                        .teamId(targetTeam.getId())
                        .type(0L)
                        .contestId(dto.getTargetContestId())
                        .build();
                targetPlayerTeamList.add(playerAndTeam);
            });
        }
        if (CollUtil.isNotEmpty(targetPlayerTeamList)) {
            iBasketballPlayerAndTeamService.saveBatch(targetPlayerTeamList);
        }
        return true;
    }
}
